package mware_lib;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import cash_access.AccountProxy;
import cash_access.AccountSkeleton;

import mware_lib.communication.Client;
import mware_lib.exceptions.RemoteException;
import mware_lib.messages.RebindBackMsg;
import mware_lib.messages.RebindMsg;
import mware_lib.messages.ResolveBackMsg;
import mware_lib.messages.ResolveMsg;
import mware_lib.ns.Data;

import cash_access.Account;
import branch_access.Manager;
import branch_access.ManagerProxy;
import branch_access.ManagerSkeleton;

public class LocalNameService extends NameService{

	
	private String host;
	private int port;
	private static int myPort = 2000;
	
	LocalNameService(String host, int port){
		this.host = host;
		this.port = port;
	}
	
	@Override
	public void rebind(Object servant, String name) {
		Client nameServer;
		if(servant != null){
			try {
				if(doesExtend(servant.getClass(), Manager.class)){
					String rebindTyp = "Manager";
					ManagerSkeleton ms = new ManagerSkeleton(myPort, (Manager)servant, host, port);
					ms.start();
					Data data = new Data(InetAddress.getLocalHost().getHostAddress(), myPort, rebindTyp);
					RebindMsg rebindMsg = new RebindMsg(name, data);
					nameServer = new Client(this.host, this.port);
					nameServer.send(rebindMsg);
					
				}else if(doesExtend(servant.getClass(), Account.class)){
					String rebindTyp = "Account";
					AccountSkeleton as = new AccountSkeleton(myPort, (Account)servant);
					as.start();
					Data data = new Data(InetAddress.getLocalHost().getHostAddress(), myPort, rebindTyp);
                    RebindMsg rebindMsg = new RebindMsg(name, data);
                    nameServer = new Client(this.host, this.port);
                    nameServer.send(rebindMsg);
				}		
				
//				RebindBackMsg rebindBackMsg = (RebindBackMsg) nameServer.receive();
//				if(rebindBackMsg != null && !rebindBackMsg.isErfolgreich()){
//                    throw new RemoteException("Fehler Rebind, beim Entfernen: Konto garnicht vorhanden");
//				}
				
			} catch (IOException e) {
				System.out.println((e.getClass().toString() + ": " + e.getMessage() + e));
			}finally{
				myPort++;
			}	
		}else{		//Objekt aus Liste l�schen; servant == null
			//String rebindTyp = "L�schen";
			
            RebindMsg rebindMsg = new RebindMsg(name, null);
            try{
            	nameServer = new Client(this.host, this.port);
            	nameServer.send(rebindMsg);
            } catch (IOException e) {
				System.out.println((e.getClass().toString() + ": " + e.getMessage() + e));
			}
		}
	}

	@Override
	public Object resolve(String name) {
		ResolveMsg resMsg = new ResolveMsg(name);
		ResolveBackMsg returnMsg = null;
		
		try {
			Client nameServer = new Client(this.host, this.port);
			nameServer.send(resMsg);
//			Data d = (ResolveBackMsg)nameServer.receive();
			returnMsg = (ResolveBackMsg)nameServer.receive();
//			nameServer.close();
		} catch (IOException e) {
			System.out.println(e.getClass().toString() + ": " + e.getMessage() + e);
		} catch (ClassNotFoundException e) {
			System.out.println(e.getClass().toString() + ": " + e.getMessage() + e);
		} 
			
		if(!(returnMsg == null)){
		
			if(returnMsg.getData() == null || returnMsg.getData().getType() == null){
				System.out.println("Resolve: Gew�nschte ID nicht vorhanden!");
			}else if(returnMsg.getData().getType().equals("Manager")){
				return new ManagerProxy(returnMsg.getData().getHost(), returnMsg.getData().getPort());
			}else if(returnMsg.getData().getType().equals("Account")){
				return new AccountProxy(name, returnMsg.getData().getHost(), returnMsg.getData().getPort());
			}
			
		}else{
			System.out.println("ResolveBackMsg ist null. Das sollte nicht sein.");
		}
		return null;
	}
	
	@SuppressWarnings("rawtypes")
	private boolean doesExtend(Class c1, Class c2){
		boolean isExtendingC = false;
		
		do{
			if(c1.equals(c2)){
				isExtendingC = true;
			}else{
				c1 = c1.getSuperclass();
			}
		}while(!isExtendingC && !c1.equals(Object.class));
		
		return isExtendingC;
	}
}
